package com.tempjob.app.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.tempjob.app.security.annotation.UserLogAnnotation;
import com.tempjob.common.businesss.mongo.entity.UserActionLog;
import com.tempjob.common.businesss.mongo.service.UserActionLogService;
import com.tempjob.common.context.UserContextManage;
import com.tempjob.common.utils.HttpContextUtils;
import com.tempjob.common.utils.IPUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
@Order(2)
public class UserActionLogAspect {
    @Lazy
    @Resource
    private UserActionLogService userActionLogService;

    /**
     * 此处的切点是注解的方式
     * 只要出现 @LogAnnotation注解都会进入
     */
    @Pointcut("@annotation(com.tempjob.app.security.annotation.UserLogAnnotation)")
    public void logPointCut() {

    }

    /**
     * 环绕增强,相当于MethodInterceptor
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //保存日志
        try {
            saveSysLog(point, time, result);
        } catch (Exception e) {
            log.error("userActionLogError:", e);
        }
        return result;
    }

    /**
     * 日志保存
     */
    private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object result) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        UserActionLog actionLog = new UserActionLog();
        actionLog.setResponse(JSON.toJSONString(result));
        UserLogAnnotation adminLogAnnotation = method.getAnnotation(UserLogAnnotation.class);
        if (adminLogAnnotation != null) {
            //注解上的描述
            actionLog.setOperation(adminLogAnnotation.title() + "-" + adminLogAnnotation.action());
        }
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        actionLog.setMethod(className + "." + methodName + "()");
        try {
            //请求的参数
            Object[] args = joinPoint.getArgs();
            String params = null;
            if (args.length != 0) {
                params = JSON.toJSONString(args, SerializerFeature.IgnoreNonFieldGetter);
            }
            if (params == null || params.length() > 5000) {
                params = null;
            }
            actionLog.setParams(params);
        } catch (Exception e) {
            log.error("sysLogError", e);
        }
        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        actionLog.setIp(IPUtils.getIpAddr(request));
        actionLog.setUrl(request.getRequestURI());
        //用户名
        if (UserContextManage.getContext() != null) {
            actionLog.setName(UserContextManage.getContext().getRealName());
            actionLog.setMobile(UserContextManage.getContext().getMobile());
            actionLog.setUserId(UserContextManage.getContext().getId());
            actionLog.setToken(UserContextManage.getAuthorization());
        }
        actionLog.setTime((int) time);
        userActionLogService.save(actionLog);
    }
}
